import 'dart:io';
import 'dart:convert';
import 'package:path_provider/path_provider.dart';
import 'package:crypto/crypto.dart';
import 'package:http/http.dart' as http;
import 'dart:developer' as developer;
import '../config/app_config.dart';
import '../di/service_locator.dart';
import '../../shared/storage/storage_service.dart';

/// 文件缓存服务（包括图片和其他文件）
/// 负责将文件从服务器下载到本地，并提供本地文件路径
class ImageCacheService {
  static final ImageCacheService _instance = ImageCacheService._internal();
  factory ImageCacheService() => _instance;
  ImageCacheService._internal();

  Directory? _cacheDir;
  final Map<String, String> _urlToLocalPath = {}; // URL -> 本地路径映射

  /// 初始化缓存目录
  Future<void> init() async {
    try {
      final appDocDir = await getApplicationDocumentsDirectory();
      _cacheDir = Directory('${appDocDir.path}/file_cache');
      if (!await _cacheDir!.exists()) {
        await _cacheDir!.create(recursive: true);
      }
      developer.log('文件缓存目录初始化: ${_cacheDir!.path}', name: 'ImageCacheService');
    } catch (e) {
      developer.log('初始化文件缓存目录失败: $e', name: 'ImageCacheService');
    }
  }

  /// 获取文件的本地缓存路径（包括图片和其他文件）
  /// 如果文件已缓存，返回本地路径；否则返回 null
  Future<String?> getLocalImagePath(String fileUrl) async {
    return getLocalFilePath(fileUrl);
  }

  /// 获取文件的本地缓存路径
  /// 如果文件已缓存，返回本地路径；否则返回 null
  Future<String?> getLocalFilePath(String fileUrl) async {
    if (_cacheDir == null) {
      await init();
    }

    if (_cacheDir == null) return null;

    // 检查内存缓存
    if (_urlToLocalPath.containsKey(fileUrl)) {
      final localPath = _urlToLocalPath[fileUrl]!;
      if (await File(localPath).exists()) {
        return localPath;
      } else {
        _urlToLocalPath.remove(fileUrl);
      }
    }

    // 生成缓存文件名（基于 URL 的哈希值）
    final hash = md5.convert(utf8.encode(fileUrl)).toString();
    final uri = Uri.tryParse(fileUrl);
    String? extension;
    if (uri != null) {
      final path = uri.path;
      final extMatch = RegExp(r'\.([^.]+)$').firstMatch(path);
      if (extMatch != null) {
        extension = extMatch.group(1);
      }
    }
    final fileName = extension != null ? '$hash.$extension' : hash;
    final localPath = '${_cacheDir!.path}/$fileName';

    // 检查文件是否存在
    if (await File(localPath).exists()) {
      _urlToLocalPath[fileUrl] = localPath;
      return localPath;
    }

    return null;
  }

  /// 下载并缓存文件（包括图片和其他文件）
  /// 返回本地文件路径
  Future<String?> downloadAndCacheImage(String fileUrl) async {
    return downloadAndCacheFile(fileUrl);
  }

  /// 下载并缓存文件
  /// 返回本地文件路径
  Future<String?> downloadAndCacheFile(String fileUrl) async {
    if (_cacheDir == null) {
      await init();
    }

    if (_cacheDir == null) {
      developer.log('缓存目录未初始化', name: 'ImageCacheService');
      return null;
    }

    // 先检查是否已缓存
    final cachedPath = await getLocalFilePath(fileUrl);
    if (cachedPath != null) {
      return cachedPath;
    }

    try {
      // 生成缓存文件名
      final hash = md5.convert(utf8.encode(fileUrl)).toString();
      final uri = Uri.tryParse(fileUrl);
      String? extension;
      if (uri != null) {
        final path = uri.path;
        final extMatch = RegExp(r'\.([^.]+)$').firstMatch(path);
        if (extMatch != null) {
          extension = extMatch.group(1);
        }
      }
      final fileName = extension != null ? '$hash.$extension' : hash;
      final localPath = '${_cacheDir!.path}/$fileName';

      // 构建请求 URL（如果是相对路径）
      String requestUrl = fileUrl;
      if (fileUrl.startsWith('/api/upload/') || fileUrl.startsWith('/upload/')) {
        final baseUrl = AppConfig.baseUrl;
        final port = AppConfig.serverPort;
        if (fileUrl.startsWith('/upload/')) {
          requestUrl = '$baseUrl:$port/api$fileUrl';
        } else {
          requestUrl = '$baseUrl:$port$fileUrl';
        }
      }

      // 获取认证 token
      final serviceLocator = ServiceLocator();
      final storageService = serviceLocator.storageService;
      final token = await storageService.getToken();

      // 下载文件
      developer.log('开始下载文件: $requestUrl', name: 'ImageCacheService');
      final headers = <String, String>{};
      if (token != null && token.isNotEmpty) {
        headers['Authorization'] = 'Bearer $token';
      }

      final response = await http.get(
        Uri.parse(requestUrl),
        headers: headers,
      ).timeout(
        const Duration(seconds: 30),
        onTimeout: () {
          throw Exception('下载文件超时');
        },
      );

      if (response.statusCode == 200) {
        // 保存到本地
        final file = File(localPath);
        await file.writeAsBytes(response.bodyBytes);
        
        // 更新内存缓存
        _urlToLocalPath[fileUrl] = localPath;
        
        developer.log('文件下载成功: $localPath', name: 'ImageCacheService');
        return localPath;
      } else {
        developer.log('下载文件失败: HTTP ${response.statusCode}', name: 'ImageCacheService');
        return null;
      }
    } catch (e) {
      developer.log('下载文件异常: $e', name: 'ImageCacheService');
      return null;
    }
  }

  /// 预加载图片（在后台下载）
  Future<void> preloadImage(String imageUrl) async {
    try {
      await downloadAndCacheImage(imageUrl);
    } catch (e) {
      developer.log('预加载图片失败: $e', name: 'ImageCacheService');
    }
  }

  /// 预加载文件（在后台下载）
  Future<void> preloadFile(String fileUrl) async {
    try {
      await downloadAndCacheFile(fileUrl);
    } catch (e) {
      developer.log('预加载文件失败: $e', name: 'ImageCacheService');
    }
  }

  /// 清理缓存（删除所有缓存的文件）
  Future<void> clearCache() async {
    if (_cacheDir == null) return;

    try {
      if (await _cacheDir!.exists()) {
        await _cacheDir!.delete(recursive: true);
        await _cacheDir!.create(recursive: true);
        _urlToLocalPath.clear();
        developer.log('文件缓存已清理', name: 'ImageCacheService');
      }
    } catch (e) {
      developer.log('清理文件缓存失败: $e', name: 'ImageCacheService');
    }
  }

  /// 获取缓存大小（字节）
  Future<int> getCacheSize() async {
    if (_cacheDir == null || !await _cacheDir!.exists()) {
      return 0;
    }

    int totalSize = 0;
    try {
      await for (final entity in _cacheDir!.list(recursive: true)) {
        if (entity is File) {
          totalSize += await entity.length();
        }
      }
    } catch (e) {
      developer.log('计算缓存大小失败: $e', name: 'ImageCacheService');
    }
    return totalSize;
  }
}


